這篇要來聊聊 Kotlin 的特性,在細數 Kotlin 有哪些特性之前,先來了解一下什麼是 Kotlin,他跟 Java 有哪些的不同呢?以下如有解釋不清或是描述有誤的地方還請大家多多指教:
來自官網上的標語,我們就來了解一下為什麼吧!Kotlin 是由 JetBrains 所開發,在 JVM 上執行可與 Java 互相作用的靜態型別程式碼語言,他也可被編譯成 JavaScript 的原始碼。而官方列出了幾個 Kotlin 會被稱作 modern programming language 的原因 (語法簡潔、code safety、可與其他語言互相操作、開發跨平台可共用的程式碼),說到這些不就代表 Kotlin 除了開發 Android 還能做更多嗎!
來看看除了 Android 還能使用 Kotlin 開發什麼,文件上提供 5 種類別的教學,分別是:
而在 2017 年 Google I/O keynote 宣布 Kotlin 將視為 Android 優先開發語言。
Kotlin 擁有 object-oriented 和 functional programming 結構,整合後發現以下幾個特點:
這邊會解釋這些特點會如何呈現,除了有標示天數的都會在這篇解說呦!
var value: String = "This is an Example"
var valueChange = "This is another one"
val i = 10
print("i = $i") // prints "i = 10"
// Java
Profile profile = new Profile(...);
// Kotlin
var profile = Profile(...)
// Java
public class Profile extends School implements Work
// Kotlin
class Profile : School, Work
// Java
switch(expression) {
case value :
// do something
break;
case value :
// do something
break;
default :
// do something
}
// Kotlin
when(expression) {
value1 -> // do something
value2 -> // do something
else -> // do something
}
Kotlin's type system is aimed at eliminating the danger of null references.
為了避免 NullPointerException
的發生,type system 區分了 nullable
和 non-null
reference
// nullable reference
var english? = "abc"
english = null
// non-null reference
var number = "123"
number = null // compilation error
只有在以下的狀況會出現 NullPointerException
:
throw NullPointerException()
!!
(表示這個參數一定為 non-null 狀態)函式程式設計簡稱 EP,是一種設計方法,先來講講 EP 會有以下幾個特性:
針對 EP 這邊有找到一篇文章的描述覺得蠻簡而易懂的:
函式就算定義為「高階函式」,也不一定就能稱為「函式程式設計」,符合函式程式設計有一定的要件,你還必須確保該函式要能「避免改變狀態」、「避免可變的資料」以及擁有「純函式」等特性。
那 Kotlin 的 Functional Programming 在哪邊呢?以下列幾個比較常見的 function:
// filter
val animals = listof("dog", "cat", "goose")
val dog = animals.filter { it == "dog" } // get dog string
// map or flatMap
val number = listof(1, 2, 3)
val double = number.map { it * 2 } // get [2, 4, 6] list
// sum
val number = listof(1, 2, 3)
val point = number.sum() // get 6
Kotlin 提供可以重新定義計算元的型態,這是什麼意思呢?來看看以下範例:
val a = 1
val b = 2
print(a.plus(b)) // get 3
// overloading example
class Point(val x: Int = 0, val y: Int = 10) {
// overloading plus function
operator fun plus(p: Point) : Point {
return Point(x + p.x, y + p.y)
}
}
...
val a = Point(3, 5)
val b = Point(-6, 8)
val sum = a + b
print("sum = ${sum.x}/${sum.y}") // get sum = -3/13
在沒有給予明確的型態,在 compiler 時我們透過 is
來 check:
fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
// or
if (x !is String) return
print(x.length) // x is automatically cast to String
}
哪些情況下是不安全的寫法呢?
// the unsafe cast in Kotlin is done by the infix operator as
val x: String = y as String
// 這個型態為 non-null,萬一 y 為 null 就會有 exception,應該寫成 nullable
val x: String? = y as String?
Singleton Pattern 是一種設計模式
Ensure a class only has one instance, and provide a global point of access to it.
- Design Patterns, Singleton Pattern
在 Kotlin 中要怎麼實現 Singleton 呢?不像 Java 有 static 來宣告靜態類別,Object
扮演個一個很重要的角色,Kotlin 提供了 Object 和 Companion Object 來實作 Singleton 的物件,Object
沒有 construct ,因為不應該在其他地方可以被創建出來。
object ProfileName {
var name = "my name"
fun ageCount() {
...
}
}
...
ProfileName.name = "your name"
print(ProfileName.name) // get your name
// if only some parts of the class are static.
class Profile {
companion object {
var name = "my name"
fun ageCount() {
...
}
}
}
...
Profile.name = "your name"
print(Profile.name) // get your name
Kotlin 提供較方便的範圍表示式
// equivalent of 1 <= i && i <= 4
if (i in 1..4) print(i)
// print 1234
for (i in 1..4) print(i)
// print 4321
for (i in 4 downTo 1) print(i)
// to iterate over numbers with an arbitrary step, print 1357
for (i in 1..8 step 2) print(i)
// i in 1 until 10, excluding 10
for (i in 1 until 10) print(i)
主構造函數
A class in Kotlin can have a primary constructor and one or more secondary constructors.
The primary constructor is a part of the class header, and it goes after the class name and optional type parameters.
將變數定義在 header 裡,不包含任何 code, 透過 init {}
來初始化
class Person constructor(firstName: String) { /*...*/ }
// 如果主構造函數沒有任何 annotiotns 或修飾符,可以省略 constructor
class Person (firstName: String) { /*...*/ }
至於次構造函數的部分就必須定義在 class 中
class Person(val pets: MutableList<Pet> = mutableListOf())
class Pet {
constructor(owner: Person) {
owner.pets.add(this) // adds this pet to the list of its owner's pets
}
}
// If the class has a primary constructor
// each secondary constructor needs to delegate to the primary constructor
class Person(val name: String) {
val children: MutableList<Person> = mutableListOf()
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
The Kotlin Blog
Why Kotlin
12 Top Kotlin Features
Functional Programming
Functional Programming wiki
Official Kotlin
Operator Overloading Example
Kotlin Singleton
Object 與 Singleton